#include "StdAfx.h"
#include "EditorHelper.h"
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <gp_Circ.hxx>
#include <gp_Pln.hxx>
#include <gp_Vec.hxx>
#include <GC_MakeArcOfCircle.hxx>
#include "ShapeReps.h"
#include "SelectionSet.h"
CEditorHelper::CEditorHelper(void)
:m_nStep(-1),
m_pSelectionSet(NULL)
{

}

CEditorHelper::~CEditorHelper(void)
{
	GetRender()->Remove(m_ShapeRep);
	delete m_pSelectionSet;
}

void CEditorHelper::Initialize(CAnyView* pView)
{
	CAnyEditor::Initialize(pView);
	m_pSelectionSet = GetRender()->CreateSelectionSet(*pView);
}
bool CEditorHelper::CreateLine(const gp_Pnt& ptStart, const gp_Pnt& ptEnd, TopoDS_Shape& shape)
{
	try
	{
		BRepBuilderAPI_MakeEdge builder(ptStart, ptEnd);
		shape = builder.Shape();
	}
	catch (...) 
	{
		return false;
	}

	return true;
}

void CEditorHelper::Render(CShapeReps& shape, bool bUpdate)
{
	// display
	GetRender()->SetColor(shape,Quantity_NOC_GREEN,false);
	GetRender()->Render(shape, bUpdate);
}

CSelectionSet& CEditorHelper::Selecter()
{
	return *m_pSelectionSet;
}

EditorState CEditorHelper::Start(void)
{
	Selecter().OpenLocalContext();

	return ES_CONTINUE;
}

void CEditorHelper::Finish(void)
{
	Selecter().CloseLocalContext();
}
//////////////////////////////////////////////////////////////////////////
CPointCapture::CPointCapture(gp_Pnt& refPoint):
m_refPoint(refPoint)
{
}

CPointCapture::~CPointCapture(void)
{
}
EditorState CPointCapture::OnLButtonDown(UINT nFlags, long x, long y)
{
	GetView()->ConvertToGrid(x,y, m_refPoint);

	return ES_FINISHED;
}
EditorState CPointCapture::OnLButtonUp(UINT nFlags, long x, long y)
{
	//V3d_Coordinate X,Y,Z;
	//GetView()->ConvertToGrid(x,y,X,Y,Z);
	//m_refPoint.SetCoord(X,Y,Z);
	GetRender()->Remove(m_ShapeRep);
	return ES_FINISHED;
}

void CPointCapture::OnMouseMove(UINT nFlags, long x, long y)
{
	GetView()->ConvertToGrid(x,y,m_refPoint);

	GetRender()->Remove(m_ShapeRep, false);
	BRepBuilderAPI_MakeVertex builder(m_refPoint);
	TopoDS_Shape shape = builder.Shape();
	m_ShapeRep = CShapeReps(shape);
	Render(m_ShapeRep, true);
}

//////////////////////////////////////////////////////////////////////////
CLengthCapture::CLengthCapture(const gp_Pnt& refStart, 
							   gp_Pnt& refEnd,
							   Standard_Real& refLength):
m_refStart(refStart),
m_refEnd(refEnd),
m_refLength(refLength)
{
}

CLengthCapture::~CLengthCapture(void)
{
}
EditorState CLengthCapture::OnLButtonDown(UINT nFlags, long x, long y)
{
	GetView()->ConvertToGrid(x,y,m_refEnd);
	m_refLength = m_refEnd.Distance(m_refStart);

	return ES_FINISHED;
}
EditorState CLengthCapture::OnLButtonUp(UINT nFlags, long x, long y)
{
	//V3d_Coordinate X,Y,Z;
	//GetView()->ConvertToGrid(x,y,X,Y,Z);
	//m_refPoint.SetCoord(X,Y,Z);
	GetRender()->Remove(m_ShapeRep);

	return ES_FINISHED;
}

void CLengthCapture::OnMouseMove(UINT nFlags, long x, long y)
{
	GetView()->ConvertToGrid(x,y,m_refEnd);
	m_refLength = m_refEnd.Distance(m_refStart);

	// remove old shape
	GetRender()->Remove(m_ShapeRep, false);

	TopoDS_Shape shape;
	if(CreateLine(m_refStart, m_refEnd, shape))
	{
		m_ShapeRep = CShapeReps(shape);

		Render(m_ShapeRep, true);

	}
}
//////////////////////////////////////////////////////////////////////////
CRectCapture::CRectCapture(const gp_Pnt& refStart, 
							   gp_Pnt& refEnd,
							   Standard_Real& refLength,
							   Standard_Real& refWidth):
m_refStart(refStart),
m_refEnd(refEnd),
m_refLength(refLength),
m_refWidth(refWidth)
{
}

CRectCapture::~CRectCapture(void)
{
}
EditorState CRectCapture::OnLButtonDown(UINT nFlags, long x, long y)
{
	GetView()->ConvertToGrid(x,y,m_refEnd);
	m_refLength = m_refEnd.X() - m_refStart.X();
	m_refWidth = m_refEnd.Y()-m_refStart.Y();

	return ES_FINISHED;
}
EditorState CRectCapture::OnLButtonUp(UINT nFlags, long x, long y)
{
	//V3d_Coordinate X,Y,Z;
	//GetView()->ConvertToGrid(x,y,X,Y,Z);
	//m_refPoint.SetCoord(X,Y,Z);
	GetRender()->Remove(m_ShapeRep);

	return ES_FINISHED;
}

void CRectCapture::OnMouseMove(UINT nFlags, long x, long y)
{
	GetView()->ConvertToGrid(x,y,m_refEnd);
	m_refLength = m_refEnd.X() - m_refStart.X();
	m_refWidth = m_refEnd.Y()-m_refStart.Y();

	// remove old shape
	GetRender()->Remove(m_ShapeRep, false);

	TopoDS_Shape shape;
	if(CreateLine(m_refStart, m_refEnd, shape))
	{
		m_ShapeRep = CShapeReps(shape);

		Render(m_ShapeRep, true);

	}
}
//////////////////////////////////////////////////////////////////////////
CHeightCapture::CHeightCapture(const gp_Pnt& refStart, 
							   gp_Pnt& refEnd,
							   Standard_Real& refHeight):
m_refStart(refStart),
m_refEnd(refEnd),
m_refHeight(refHeight)
{
}

CHeightCapture::~CHeightCapture(void)
{

}


EditorState CHeightCapture::OnLButtonDown(UINT nFlags, long x, long y)
{
	GetView()->Convert(x,y, m_refStart, m_refEnd);
	m_refHeight = m_refEnd.Distance(m_refStart);

	return ES_FINISHED;
}
EditorState CHeightCapture::OnLButtonUp(UINT nFlags, long x, long y)
{
	//V3d_Coordinate X,Y,Z;
	//GetView()->ConvertToGrid(x,y,X,Y,Z);
	//m_refPoint.SetCoord(X,Y,Z);

	GetRender()->Remove(m_ShapeRep);

	return ES_FINISHED;
}

void CHeightCapture::OnMouseMove(UINT nFlags, long x, long y)
{
	GetView()->Convert(x,y, m_refStart, m_refEnd);
	m_refHeight = m_refEnd.Distance(m_refStart);

	// remove old shape
	GetRender()->Remove(m_ShapeRep, false);

	TopoDS_Shape shape;
	if(CreateLine(m_refStart, m_refEnd, shape))
	{
		m_ShapeRep = CShapeReps(shape);
		Render(m_ShapeRep, true);
	}
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
CAngleCapture::CAngleCapture(const gp_Pnt& refCenter,
							 const gp_Pnt& refStart, 
							 const gp_Dir& refPlaneNormal,
							   gp_Pnt& refEnd,
							   Standard_Real& refAngle):
m_refCenter(refCenter),
m_refStart(refStart),
m_refPlaneNormal(refPlaneNormal),
m_refEnd(refEnd),
m_refAngle(refAngle)
{
	
}

CAngleCapture::~CAngleCapture(void)
{
	GetRender()->Remove(m_lineStart, false);
	GetRender()->Remove(m_lineEnd, false);
	GetRender()->Remove(m_ShapeRep);
}
void CAngleCapture::ComputeAngle(long x, long y)
{
	gp_Pln plane(m_refCenter, m_refPlaneNormal);
	GetView()->Convert(x,y, plane, m_refEnd);

	gp_Vec linStart(m_refCenter, m_refStart);
	gp_Vec linEnd(m_refCenter, m_refEnd);
	gp_Vec positive(m_refPlaneNormal);
	m_refAngle = linStart.AngleWithRef(linEnd, positive);

	m_refEnd = m_refStart;
	m_refEnd.Rotate(gp_Ax1(m_refCenter, m_refPlaneNormal), m_refAngle);
}

EditorState CAngleCapture::OnLButtonDown(UINT nFlags, long x, long y)
{
	ComputeAngle(x, y);

	return ES_FINISHED;
}
EditorState CAngleCapture::OnLButtonUp(UINT nFlags, long x, long y)
{
	//V3d_Coordinate X,Y,Z;
	//GetView()->ConvertToGrid(x,y,X,Y,Z);
	//m_refPoint.SetCoord(X,Y,Z);
	GetRender()->Remove(m_lineStart, false);
	GetRender()->Remove(m_lineEnd, false);
	GetRender()->Remove(m_ShapeRep);

	return ES_FINISHED;
}

void CAngleCapture::OnMouseMove(UINT nFlags, long x, long y)
{
	ComputeAngle(x, y);

	// remove old shape
	GetRender()->Remove(m_ShapeRep, false);
	GetRender()->Remove(m_lineStart, false);
	GetRender()->Remove(m_lineEnd, false);
	TopoDS_Shape lineStart;
	if(CreateLine(m_refCenter, m_refStart, lineStart))
	{
		m_lineStart = CShapeReps(lineStart);
		// display
		Render(m_lineStart, false);
	}

	TopoDS_Shape lineEnd;
	if(CreateLine(m_refCenter, m_refEnd, lineEnd))
	{
		m_lineEnd = CShapeReps(lineEnd);
		// display
		Render(m_lineEnd, false);
	}


	try
	{
		gp_Ax2 aix(m_refCenter, m_refPlaneNormal);
		gp_Circ circle(aix, m_refStart.Distance(m_refCenter));
		GC_MakeArcOfCircle make(circle, m_refStart, m_refEnd, false);
		const Handle_Geom_TrimmedCurve  curve = make.Value();
		BRepBuilderAPI_MakeEdge builder(curve);
		TopoDS_Shape arcShape = builder.Shape();
		m_ShapeRep = CShapeReps(arcShape);
		Render(m_ShapeRep, true);
	}
	catch (...)
	{
	}
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
CShapeCapture::CShapeCapture(TopAbs_ShapeEnum nShapeType, 
		TopoDS_Shape& shape,
		gp_Pnt& refCapturePt):
m_nShapeType(nShapeType),
m_Shape(shape),
m_refPoint(refCapturePt)
{
}

CShapeCapture::~CShapeCapture(void)
{

}


EditorState CShapeCapture::OnLButtonDown(UINT nFlags, long x, long y)
{	
	CAutoSelectMode autoSelectMode(Selecter(), m_nShapeType);

	AIS_StatusOfPick status = Selecter().Select(x, y);
	if(status != AIS_SOP_OneSelected)
		return ES_CONTINUE;

	if(!Selecter().GetSelected(m_Shape))
		return ES_CONTINUE;

	GetView()->ConvertToGrid(x,y,m_refPoint); 

	return ES_FINISHED;
}
EditorState CShapeCapture::OnLButtonUp(UINT nFlags, long x, long y)
{
	return ES_FINISHED;
}

void CShapeCapture::OnMouseMove(UINT nFlags, long x, long y)
{
	CAutoSelectMode autoSelectMode(Selecter(),m_nShapeType);

	Selecter().DynamicSense(x, y);
}

void CShapeCapture::Initialize(CAnyView* pView)
{
	CEditorHelper::Initialize(pView);

}
//////////////////////////////////////////////////////////////////////////